//
// Created by ych on 2/15/24.
//

#ifndef MATINTERPRETER_GENERATOR_H
#define MATINTERPRETER_GENERATOR_H

#include "parser.h"
#include "../vm/memory.h"
#include "../vm/CFunction.h"
#include "../machine/ych_state.h"

#define SEM_OK 0
#define SEM_ERROR 1
#define SEM_MEM_OVERFLOW_ERROR 2
#define SEM_TYPE_ERROR 3
#define SEM_REDECLARE_VAR_ERROR 4
#define SEM_UNDEFINED_VAR_ERROR 5
#define SEM_ARRAY_LENGTH_ERROR 6
#define SEM_BREAK_NOT_IN_LOOP_STRUCT_ERROR 7
#define SEM_UNDEFINED_FUNCTION_ERROR 8
#define SEM_FUNC_PARAM_ERROR 9
#define SEM_REDEFINED_FUNC_ERROR 10
#define SEM_FUNC_CAN_NOT_DEFINE_IN_FUNC 11
#define SEM_RETURN_NOT_IN_FUNC 12

#define FIRST_ACTION LAST_NT_
typedef enum AC_ {
    AC_PUSH_CONST = FIRST_ACTION,
    AC_STAGE,
    AC_MALLOC_VAR,
    AC_ASSIGN_FIRST,
    AC_SEM_POP, AC_POP,
    AC_PUSH_VAR, AC_PUSH_FUNC,
    AC_ADD, AC_SUB, AC_MUL, AC_DIV, AC_INNER, AC_MOD, AC_POW,
    AC_LESS, AC_GREATER, AC_LESSEQUAL, AC_GREATEREQUAL, AC_EQUAL, AC_NOTEQUAL, AC_NEG,
    AC_OR, AC_AND, AC_NOT,
    AC_ASSIGN_END, AC_SEM_PUSH_ASSIGN,
    AC_FUNC_COUNT_PARAM, AC_FUNC_END,
    AC_IF_JUDGE, AC_WHILE_JUDGE,
    AC_SEM_PUSH_WHILE, AC_WHILE_END, AC_WHILE_BREAK,
    AC_IF_END, AC_SEM_PUSH_ELSE, AC_ELSE_END,
    AC_DEF_FUNC_START, AC_DEF_COUNT_PARAMS, AC_RETURN, AC_DEF_FUNC_END,
    AC_MAT_COUNT_ROW, AC_MAT_COUNT_COL, AC_MAT_END, AC_MAT_START,
    AC_INDEX, AC_MAT_INDEX, AC_ARRAY_START, AC_ARRAY_VALUE_ASSIGN, AC_ARRAY_END,AC_SET_ARRAY_LENGTH
} AC_;

void loadClib(Parser *parser);

static void codeOPK(CState *c_state, Uint opcode, Uint k);

static void codeKABC(CState *c_state, Uint opcode, Uint k, Uint a, Uint b, Uint c);

static void codeKABx(CState *c_state, Uint opcode, Uint k, Uint a, Uint bx);

static void codeKBC(CState *c_state, Uint opcode, Uint k, Uint b, Uint c);

int ac(Parser *parser, T ac);

static void genCodeByMInfo(Parser *parser, MInfo m, Uint R);

static int findVar(VarHashMap *map, char *string, Uint *p);

static int findFunc(Parser *parser, char *string, FuncInfo *func_info);

static int allocVar(Parser *parser, VarHashMap *map, char *string, Uint *p);

static int allocInnerVar(Parser *parser, VarHashMap *map, char *string, Uint *p);

static Uint getIntConstP(Parser *parser, Int i);

static Uint getFloatConstP(Parser *parser, Float f);

static Uint getStringConstP(Parser *parser, char *string);

static int acMallocVar(Parser *parser);

static int acAssignFirst(Parser *parser);

static int acSemPop(Parser *parser);

static int acPop(Parser *parser);

static int acStage(Parser *parser);

static int acPushConst(Parser *parser);

static int acPushVar(Parser *parser);

static int acPushFunc(Parser *parser);

static int acFuncCount(Parser *parser);

static int acFuncEnd(Parser *parser);

static int acCompute(Parser *parser, Uint OPCODE, int isInterchange);

static int acNeg(Parser *parser);

static int acNot(Parser *parser);

static int acInner(Parser *parser);

static int acAssignEnd(Parser *parser);

static int acSemPushAssign(Parser *parser);

static int acSemPushWhile(Parser *parser);

static int acIfJudge(Parser *parser);

static int acWhileJudge(Parser *parser);

static int acWhileEnd(Parser *parser);

static int acWhileBreak(Parser *parser);

static int acIfEnd(Parser *parser);

static int acSemPushElse(Parser *parser);

static int acElseEnd(Parser *parser);

static int acDefFuncStart(Parser *parser);

static int acDefCountParams(Parser *parser);

static int acReturn(Parser *parser);

static int acDefFuncEnd(Parser *parser);

static int acMatCountRow(Parser *parser);

static int acMatCountCol(Parser *parser);

static int acMatStart(Parser *parser);

static int acMatEnd(Parser *parser);

static int acIndex(Parser *parser);

static int acMatIndex(Parser *parser);

static int acArrayStart(Parser *parser);

static int acArrayValueAssign(Parser *parser);

static int acArrayEnd(Parser *parser);
static int acSetArrayLength(Parser *parser);
static void throwCoder(Parser *parser, int code);

#endif //MATINTERPRETER_GENERATOR_H
